package vip.web3.admin.sys.service.impl.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.web3.admin.common.enums.SysWalletUpdateEnum;
import vip.web3.admin.common.utils.Query;
import vip.web3.admin.sys.dao.biz.AOrderDao;
import vip.web3.admin.sys.dao.biz.ARecordDao;
import vip.web3.admin.sys.dao.biz.AUserDao;
import vip.web3.admin.sys.dao.biz.AUserWalletDao;
import vip.web3.admin.sys.entity.biz.AOrderEntity;
import vip.web3.admin.sys.entity.biz.ARecordEntity;
import vip.web3.admin.sys.entity.biz.AUserEntity;
import vip.web3.admin.sys.entity.biz.AUserWalletEntity;
import vip.web3.admin.sys.form.user.UserWalletPageForm;
import vip.web3.admin.sys.form.user.WalletUpdateForm;
import vip.web3.admin.sys.mapper.AUserWalletMapper;
import vip.web3.admin.sys.service.biz.IARecordService;
import vip.web3.admin.sys.service.biz.IAUserService;
import vip.web3.admin.sys.service.biz.IAUserWalletService;
import vip.web3.admin.sys.service.sys.SysConfigService;
import vip.web3.admin.sys.shiro.ShiroUtils;
import vip.web3.admin.sys.vo.biz.BizUserWalletVo;
import vip.web3.admin.sys.vo.biz.UserWalletVo;
import vip.web3.admin.sys.vo.biz.export.ExWalletVo;
import vip.web3.common.enums.ActiveEnum;
import vip.web3.common.enums.AssetEnum;
import vip.web3.common.enums.OperateEnum;
import vip.web3.common.exception.RRException;
import vip.web3.common.utils.Convert;
import vip.web3.common.utils.DateUtils;
import vip.web3.common.utils.PageUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 用户钱包Service业务层处理
 */
@Service
public class AUserWalletServiceImpl extends ServiceImpl<AUserWalletDao, AUserWalletEntity> implements IAUserWalletService {


    @Autowired
    private AUserWalletDao aUserWalletDao;
    @Autowired
    private AUserDao aUserDao;
    @Autowired
    private ARecordDao aRecordDao;
    @Resource
    private AOrderDao aOrderDao;

    @Resource
    private SysConfigService sysConfigService;
    @Resource
    private IAUserWalletService iAUserWalletService;
    @Resource
    private IARecordService iARecordService;
    @Resource
    private IAUserService userService;


    /**
     * 批量删除用户钱包
     *
     * @param ids 需要删除的用户钱包主键
     * @return 结果
     */
    @Override
    public int deleteAUserWalletByIds(String ids) {
        return this.baseMapper.deleteAUserWalletByIds(Convert.toIntArray(ids));
    }


    @Override
    public AUserWalletEntity findByUserId(Integer userId) {
        QueryWrapper<AUserWalletEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWallet(AUserWalletEntity wallet, Integer type, BigDecimal amount1, BigDecimal amount2) {
        int update = 0;
        if (type.intValue() == AssetEnum.TYPE1.getCode().intValue()) {
            update = baseMapper.updateAmountCny(wallet.getId(), amount1, wallet.getVersion());
        } else if (type.intValue() == AssetEnum.TYPE2.getCode().intValue()) {
            update = baseMapper.updateAmountUsdt(wallet.getId(), amount1, wallet.getVersion());
        } else if (type.intValue() == AssetEnum.TYPE3.getCode().intValue()) {
            update = baseMapper.updateWithdrawCny(wallet.getId(), amount1, wallet.getVersion());
        } else if (type.intValue() == AssetEnum.TYPE4.getCode().intValue()) {
            update = baseMapper.updateWithdrawUsdt(wallet.getId(), amount1, wallet.getVersion());
        } else if (type.intValue() == AssetEnum.TYPE5.getCode().intValue()) {
            update = baseMapper.updateMixCny(wallet.getId(), amount1, amount2, wallet.getVersion());
        } else if (type.intValue() == AssetEnum.TYPE6.getCode().intValue()) {
            update = baseMapper.updateMixUsdt(wallet.getId(), amount1, amount2, wallet.getVersion());
        }
        if (update < 1) {
            log.error("修改用户钱包失败, 用户ID:" + wallet.getUserId());
            throw new RRException("更新用户资产失败, 请稍后重试!");
        }
    }

    @Override
    public PageUtils pageWallets(Map<String, Object> params, UserWalletPageForm form) {

        IPage<UserWalletVo> page = this.baseMapper.pageWallets(new Query<UserWalletVo>().getPage(params), params, form);
        List<BizUserWalletVo> walletVoList = AUserWalletMapper.INSTANCE.toAdminBizUserWalletVoList(page.getRecords());

        return new PageUtils(walletVoList, page);
    }

    @Override
    public List<ExWalletVo> export(Map<String, Object> params, UserWalletPageForm form) {
        return this.baseMapper.exWallets(params, form);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sysUpdateWallet(WalletUpdateForm form) {

        SysWalletUpdateEnum updateEnum = SysWalletUpdateEnum.get(form.getType());
        if (Objects.isNull(updateEnum)) {
            throw new RRException("操作类型错误!!", -1);
        }
        AUserWalletEntity wallet = this.aUserWalletDao.selectById(form.getId());
        if (Objects.isNull(wallet)) {
            throw new RRException("用户错误!!", -1);
        }
        AUserEntity user = this.aUserDao.selectById(wallet.getUserId());
        if (Objects.isNull(user)) {
            throw new RRException("用户不存在!!", -1);
        }
//        if (form.getWalletType() != null) {
//            if (form.getWalletType().equals(1) || form.getWalletType().equals(2)) {
//                wallet.setType(form.getWalletType());
//                aUserWalletDao.updateById(wallet);
//                return;
//            }
//        }
        if (SysWalletUpdateEnum.AMOUNT_CNY.equals(updateEnum)) {
            if (form.getAmount().compareTo(BigDecimal.ZERO) < 0 && wallet.getAmountCny().compareTo(form.getAmount().abs()) < 0) {
                throw new RRException("参投余额_人民币不足!!", -1);
            }
            this.aUserWalletDao.updateAmountCny(wallet.getId(), form.getAmount(), wallet.getVersion());
            this.aRecordDao.insert(this.createUserRecord(form, user));
            setUserPersonalLevelByCnyAndUsdt(wallet.getUserId(), 1);  // 个人累计业绩奖励
        }
        if (SysWalletUpdateEnum.AMOUNT_USDT.equals(updateEnum)) {
            if (form.getAmount().compareTo(BigDecimal.ZERO) < 0 && wallet.getAmountUsdt().compareTo(form.getAmount().abs()) < 0) {
                throw new RRException("参投余额_USDT不足!!", -1);
            }
            this.aUserWalletDao.updateAmountUsdt(wallet.getId(), form.getAmount(), wallet.getVersion());
            this.aRecordDao.insert(this.createUserRecord(form, user));
            setUserPersonalLevelByCnyAndUsdt(wallet.getUserId(), 2);  // 个人累计业绩奖励
        }
        if (SysWalletUpdateEnum.WITHDRAW_CNY.equals(updateEnum)) {
            if (form.getAmount().compareTo(BigDecimal.ZERO) < 0 && wallet.getWithdrawCny().compareTo(form.getAmount().abs()) < 0) {
                throw new RRException("提现余额_人民币不足!!", -1);
            }
            this.aUserWalletDao.updateWithdrawCny(wallet.getId(), form.getAmount(), wallet.getVersion());
        }
        if (SysWalletUpdateEnum.WITHDRAW_USDT.equals(updateEnum)) {
            if (form.getAmount().compareTo(BigDecimal.ZERO) < 0 && wallet.getWithdrawUsdt().compareTo(form.getAmount().abs()) < 0) {
                throw new RRException("提现余额_USDT不足!!", -1);
            }
            this.aUserWalletDao.updateWithdrawUsdt(wallet.getId(), form.getAmount(), wallet.getVersion());
        }
        //必须是激活用户
        if (ActiveEnum.ACTIVE.equals(ActiveEnum.get(user.getActive()))) {
            handleTeamLevel(user);
            userService.quarterReward(user.getId());
        }
        if (!form.getType().equals(1) && !form.getType().equals(2)) {
            this.aRecordDao.insert(this.createRecord(form, user));
        }
    }

    private void handleTeamLevel(AUserEntity user) {
        //更新开始日期和结束日期
        //更新开始日期和结束日期
        Date startDate = null == user.getActiveStart() ? new Date() : user.getActiveStart();
        Integer day = DateUtils.diffDate(new Date(), startDate);
        Integer index = (int) Math.ceil(day / 30);
        user.setActiveTeamBegin(DateUtils.addDateDays(user.getCreateTime(), (index - 1) * 30));
        user.setActiveTeamEnd(DateUtils.addDateDays(user.getCreateTime(), index * 30));

        LambdaQueryWrapper<AOrderEntity> query = new LambdaQueryWrapper<>();
        query.eq(AOrderEntity::getUserId, user.getId());
        query.ge(AOrderEntity::getCreateDate, user.getActiveTeamBegin());
        query.lt(AOrderEntity::getCreateDate, user.getActiveTeamEnd());
        Integer orderCount = aOrderDao.selectCount(query);
        //根据日期查询总金额
        LambdaQueryWrapper<ARecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ARecordEntity::getUserId, user.getId());
        queryWrapper.eq(ARecordEntity::getType, 1); //充值流水
        queryWrapper.ge(ARecordEntity::getCreateDate, user.getActiveTeamBegin());
        queryWrapper.lt(ARecordEntity::getCreateDate, user.getActiveTeamEnd());
        List<ARecordEntity> recordEntities = aRecordDao.selectList(queryWrapper);
        Double orderMoney = recordEntities.stream().mapToDouble(a -> a.getAmount().doubleValue()).sum();
        //查询日期内交易金额

        String team1 = sysConfigService.getValue("alloy:team:level:count:1");
        if (orderCount >= Integer.parseInt(team1.split("_")[0]) && orderMoney > Double.parseDouble(team1.split("_")[1])) {
            user.setTeamLevel(1);
            user.setTeamName("合金初创者");
        }
        // 合金中创者：月单数要求三级内50单（大于等于）同时充值流水要求达50000元，领取月总充值的百分之10，连续3个月完成领取季度充值奖励总额的百分之12，连续6个月完成领取半年度充值奖励总额的百分之15，连续10-12个月完成领取年度充值奖励总额的百分之18，并邀请参加合金工业年度领导人峰会。
        String team2 = sysConfigService.getValue("alloy:team:level:count:2");
        if (orderCount >= Integer.parseInt(team2.split("_")[0]) && orderMoney > Double.parseDouble(team2.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 2) {
                user.setTeamLevel(2);
                user.setTeamName("合金中创者");
            }
        }
        //** 合金顶创者：月单数要求三级内300单（大于等于）同时充值流水要求达300000元，领取总充值的百分之15，连续3个月完成领取季度充值奖励总额的百分之18，连续6个月完成领取半年度充值奖励总额的百分之20，连续10-12个月完成领取年度充值奖励总额的百分之22，赠送宝马5系轿车一辆价值40万元，并邀请参加合金工业年度领导人峰会。
        String team3 = sysConfigService.getValue("alloy:team:level:count:3");
        if (orderCount >= Integer.parseInt(team3.split("_")[0]) && orderMoney > Double.parseDouble(team3.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 3) {
                user.setTeamLevel(3);
                user.setTeamName("合金顶创者");
            }
        }
        // 合金战略合伙人：月单数要求三级内1000（大于等于）同时充值流水要求达1000000元，领取总充值百分之20，连续3个月完成领取季度充值奖励总额的百分之22，连续6个月完成领取半年度充值奖励总额的百分之25，连续10-12个月完成领取年度充值奖励的百分之28，赠送奔驰S480轿车一辆价值150万，并邀请参加合金工业年度领导人峰会
        String team4 = sysConfigService.getValue("alloy:team:level:count:4");
        if (orderCount >= Integer.parseInt(team4.split("_")[0]) && orderMoney > Double.parseDouble(team4.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 4) {
                user.setTeamLevel(4);
                user.setTeamName("合金战略合伙人");
            }
        }

        aUserDao.updateById(user);

    }


    private ARecordEntity createRecord(WalletUpdateForm form, AUserEntity user) {
        SysWalletUpdateEnum updateEnum = SysWalletUpdateEnum.get(form.getType());
        OperateEnum operateEnum = null;
        if (SysWalletUpdateEnum.AMOUNT_CNY.equals(updateEnum)) {
            operateEnum = OperateEnum.ADMIN21;
        }
        if (SysWalletUpdateEnum.AMOUNT_USDT.equals(updateEnum)) {
            operateEnum = OperateEnum.ADMIN22;
        }
        if (SysWalletUpdateEnum.WITHDRAW_CNY.equals(updateEnum)) {
            operateEnum = OperateEnum.ADMIN23;
        }
        if (SysWalletUpdateEnum.WITHDRAW_USDT.equals(updateEnum)) {
            operateEnum = OperateEnum.ADMIN24;
        }
        ARecordEntity record = new ARecordEntity();
        record.setUserId(user.getId());
        record.setMobile(user.getMobile());
        record.setType(operateEnum.getType());
        record.setTypeName(operateEnum.getMark());
        record.setRemark(ShiroUtils.getUserEntity().getUsername() + ":" + updateEnum.getRemark(form.getAmount()));
        record.setAmount(form.getAmount());
        record.setFee(BigDecimal.ZERO);
        record.setStatus(1);
        record.setCreateDate(new Date());
        record.setUpdateDate(new Date());
        return record;
    }

    private ARecordEntity createUserRecord(WalletUpdateForm form, AUserEntity user) {
        SysWalletUpdateEnum updateEnum = SysWalletUpdateEnum.get(form.getType());
        OperateEnum operateEnum = OperateEnum.TYPE1;
        Integer operate = null;
        if (SysWalletUpdateEnum.AMOUNT_CNY.equals(updateEnum)) {
            operate = 1;
        }
        if (SysWalletUpdateEnum.AMOUNT_USDT.equals(updateEnum)) {
            operate = 2;
        }
        ARecordEntity record = new ARecordEntity();
        record.setUserId(user.getId());
        record.setMobile(user.getMobile());
        record.setType(operateEnum.getType());
        record.setTypeName(operateEnum.getMark());
        record.setRemark(ShiroUtils.getUserEntity().getUsername() + ":" + updateEnum.getRemark(form.getAmount()));
        record.setAmount(form.getAmount());
        record.setOperateType(operate);
        record.setFee(BigDecimal.ZERO);
        record.setStatus(1);
        record.setCreateDate(new Date());
        record.setUpdateDate(new Date());
        return record;
    }

    /**
     * 个人累计业绩奖励 获得 级别设置
     *
     * @param userId
     */
    public void setUserPersonalLevelByCnyAndUsdt(Integer userId, Integer type) {
        AUserEntity user = this.aUserDao.selectById(userId);
        // 获取当前时间
        Date endDate = new Date();
        // 获取本月第一天的 00:00:00
        Calendar calendar = Calendar.getInstance();
        // 将时间设置为当月第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        // 将小时、分钟、秒、毫秒设为0
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date startDate = calendar.getTime();

        String personal1_ = sysConfigService.getValue("alloy:personal:level:limit:1");
        BigDecimal personal1limit = new BigDecimal(personal1_.split("_")[0]);
        BigDecimal personal1rate = new BigDecimal(personal1_.split("_")[1]);

        String personal2_ = sysConfigService.getValue("alloy:personal:level:limit:2");
        BigDecimal personal2limit = new BigDecimal(personal2_.split("_")[0]);
        BigDecimal personal2rate = new BigDecimal(personal2_.split("_")[1]);

        String personal3_ = sysConfigService.getValue("alloy:personal:level:limit:3");
        BigDecimal personal3limit = new BigDecimal(personal3_.split("_")[0]);
        BigDecimal personal3rate = new BigDecimal(personal3_.split("_")[1]);

        String personal4_ = sysConfigService.getValue("alloy:personal:level:limit:4");
        BigDecimal personal4limit = new BigDecimal(personal4_.split("_")[0]);
        BigDecimal personal4rate = new BigDecimal(personal4_.split("_")[1]);

        String personal5_ = sysConfigService.getValue("alloy:personal:level:limit:5");
        BigDecimal personal5limit = new BigDecimal(personal5_.split("_")[0]);
        BigDecimal personal5rate = new BigDecimal(personal5_.split("_")[1]);

        List<BigDecimal> limitList = new ArrayList<>();
        limitList.add(personal5limit);
        limitList.add(personal4limit);
        limitList.add(personal3limit);
        limitList.add(personal2limit);
        limitList.add(personal1limit);

        List<BigDecimal> rateList = new ArrayList<>();
        rateList.add(personal5rate);
        rateList.add(personal4rate);
        rateList.add(personal3rate);
        rateList.add(personal2rate);
        rateList.add(personal1rate);

        // 个人累计业绩奖励
        BigDecimal performance = aRecordDao.selectTotalRecordAmount(userId, Integer.valueOf(OperateEnum.TYPE1.getType()));
        int personalLevel = null == user.getPersonalLevel() ? 0 : user.getPersonalLevel();
        // 只升不降
        if (performance.compareTo(limitList.get(0)) >= 0) {
            if (personalLevel < 5) {
                user.setPersonalLevel(5);
                user.setPersonalName("战略合金玩家");
            }
        } else if (performance.compareTo(limitList.get(1)) >= 0) {
            if (personalLevel < 4) {
                user.setPersonalLevel(4);
                user.setPersonalName("大师合金玩家");
            }
        } else if (performance.compareTo(limitList.get(2)) >= 0) {
            if (personalLevel < 3) {
                user.setPersonalLevel(3);
                user.setPersonalName("专业合金玩家");
            }
        } else if (performance.compareTo(limitList.get(3)) >= 0) {
            if (personalLevel < 2) {
                user.setPersonalLevel(2);
                user.setPersonalName("资深合金玩家");
            }
        } else if (performance.compareTo(limitList.get(4)) >= 0) {
            if (personalLevel < 1) {
                user.setPersonalLevel(1);
                user.setPersonalName("初级合金玩家");
            }
        }

        // 更新等级后, 计算奖励比例
        BigDecimal reward = BigDecimal.ZERO;
        int newLevel = null == user.getPersonalLevel() ? 0 : user.getPersonalLevel();
        if (newLevel >= 5) {
            reward = performance.multiply(rateList.get(0));
        } else if (newLevel >= 4) {
            reward = performance.multiply(rateList.get(1));
        } else if (newLevel >= 3) {
            reward = performance.multiply(rateList.get(2));
        } else if (newLevel >= 2) {
            reward = performance.multiply(rateList.get(3));
        } else if (newLevel >= 1) {
            reward = performance.multiply(rateList.get(4));
        }
        int num = aRecordDao.selectCountIncomeNumRecord(userId, OperateEnum.TYPE10.getType()); //查询是否有 发放记录
        if (reward.compareTo(BigDecimal.ZERO) > 0 && num == 0) {
            // 发放奖励 操作钱包
            AUserWalletEntity path1Wallet = iAUserWalletService.findByUserId(user.getId());
            iAUserWalletService.updateWallet(path1Wallet, AssetEnum.TYPE3.getCode(), reward, BigDecimal.ZERO);
            // 添加记录
            iARecordService.addRewardRecord(user.getId(),
                    user.getMobile(),
                    OperateEnum.TYPE10.getType(),
                    OperateEnum.TYPE10.getMark(),
                    user.getPersonalName() + " :" + OperateEnum.TYPE10.getDesc(),
                    reward,
                    BigDecimal.ZERO,
                    type == 1 ? OperateEnum.OPERATE_TYPE1.getType() : OperateEnum.OPERATE_TYPE2.getType(),
                    "", AssetEnum.STATUS1.getCode()
            );
            // 更新执行时间
            String format = DateUtils.format(new Date(), DateUtils.DATE_PATTERN);
            try {
                Date parse = DateUtils.parse(format + " 00:00:00", DateUtils.DATE_TIME_PATTERN);
                user.setActiveStart(parse);
                user.setActiveEnd(DateUtils.addDateDays(parse, 30));
            } catch (Exception ex) {
            }
            aUserDao.updateById(user);
        }
    }
}
